﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nihongo.Verbs;

namespace Nihongo
{
    public abstract class Verb : IVerb
    {
        private const string Masu = "ます";
        private const string Mashita = "ました";
        private const string Masen = "ません";
        private const string MasenDeshita = "ませんでした";

        private readonly Word _plainForm;
        private readonly Word _root;

        protected Verb(string plainForm, string plainFormKana)
        {
            _plainForm = new Word(plainForm, plainFormKana);
            _root = _plainForm.TrimEnd(1);
        }

        protected abstract string PlainPresentNegativeEnding { get; }

        protected abstract string PlainPastNegativeEnding { get; }

        protected abstract string PlainPastEnding { get; }

        protected abstract string TeEnding { get; }

        protected abstract string ContinuousEnding { get; }

        /// <summary>
        /// The type of verb.
        /// </summary>
        public abstract VerbType VerbType { get; }

        public Word Root
        {
            get { return _root; }
        }

        public static Verb Create(string plainForm, string plainFormKana)
        {
            if (string.IsNullOrEmpty(plainForm))
            {
                throw new ArgumentException("Empty strings or nulls are not valid arguments.", "plainForm");
            }
            if (string.IsNullOrEmpty(plainFormKana))
            {
                throw new ArgumentException("Empty strings or nulls are not valid arguments.", "plainFormKana");
            }

            string ending = plainForm.Substring(plainForm.Length - 1);

            switch (ending)
            {
                case "う":
                    return new GodanUVerb(plainForm, plainFormKana);
                case "く":
                    return new GodanKuVerb(plainForm, plainFormKana);
                case "ぐ":
                    throw new NotImplementedException();
                case "す":
                    throw new NotImplementedException();
                case "つ":
                    throw new NotImplementedException();
                case "ぬ":
                    throw new NotImplementedException();
                case "ぶ":
                    throw new NotImplementedException();
                case "む":
                    throw new NotImplementedException();
                case "る":
                    return new IchidanRuVerb(plainForm, plainFormKana);
            }

            // If we get here then the word isn't a verb...
            throw new ArgumentException("The word is not a plain form verb.", "plainForm");
        }

        public Word PlainPresentForm
        {
            get { return _plainForm; }
        }

        public Word PlainPastForm
        {
            get { return Word.Concat(Root, PlainPastEnding); }
        }

        public Word PlainPresentNegativeForm
        {
            get { return Word.Concat(Root, PlainPresentNegativeEnding); }
        }

        public Word PlainPastNegativeForm
        {
            get { return Word.Concat(Root, PlainPastNegativeEnding); }
        }

        public Word MasuPresentForm
        {
            get { return Word.Concat(ContinuousForm, Masu); }
        }

        public Word MasuPresentNegativeForm
        {
            get { return Word.Concat(ContinuousForm, Masen); }
        }

        public Word MasuPastForm
        {
            get { return Word.Concat(ContinuousForm, Mashita); }
        }

        public Word MasuPastNegativeForm
        {
            get { return Word.Concat(ContinuousForm, MasenDeshita); }
        }

        public Word TeForm
        {
            get { return Word.Concat(Root, TeEnding); }
        }

        public Word ContinuousForm
        {
            get { return Word.Concat(Root, ContinuousEnding); }
        }

        public Word GetVerb(VerbForm verbForm)
        {
            switch (verbForm)
            {
                case VerbForm.PlainPresentForm:
                    return PlainPresentForm;
                case VerbForm.PlainPastForm:
                    return PlainPastForm;
                case VerbForm.PlainPresentNegativeForm:
                    return PlainPresentNegativeForm;
                case VerbForm.PlainPastNegativeForm:
                    return PlainPastNegativeForm;
                case VerbForm.MasuPresentForm:
                    return MasuPresentForm;
                case VerbForm.MasuPresentNegativeForm:
                    return MasuPresentNegativeForm;
                case VerbForm.MasuPastForm:
                    return MasuPastForm;
                case VerbForm.MasuPastNegativeForm:
                    return MasuPastNegativeForm;
                case VerbForm.TeForm:
                    return TeForm;
                case VerbForm.ContinuousForm:
                    return ContinuousForm;
            }

            throw new NotImplementedException("Oops! That verb form (" + verbForm + ") has not been implemented yet.");
        }

        public override string ToString()
        {
            return _plainForm.ToString();
        }
    }
}
